# write by hasaki
# first edit on 2018/12/28
# last change on 2019/01/16
# 常鸿量化机的大策略
import json

import os
import socket
import datetime

from hashakisea.engine.log.logSystem import SaveShelveOnce,SmallSaveCSV

class BigStrategy:
    def __init__(self):
        self.this_name=None                           # 大策略的名字

        self.save=SaveShelveOnce()                    # 保存下单数据，只保存当前的数据，也保存一条
        self.save_big_order=SmallSaveCSV()            # 保存大策略的下单
        self.orderList=[]                             # 所有小策略的下单结果
        self.csv_header=None                          # 保存csv数据的数据头
        self.file_name=None                           # 保存文件的名字

        self.socket=socket.socket()                   # 通过socket获取小策略的下单数据
        self.addr=None                                # 通信地址
        self.port=None                                # 通信端口

        self.save_file_path=None                      # 保存路径
        self.save_file_name=None                      # 保存文件名
        self.save_key_name=None                       # 保存用到的数据库键值

        self.big_order={}                             # 大策略的订单
        self.strategy_data=None                       # 用于保存有多少个策略

    # ---------------------------------------------------------------------
    # 数据进来部分
    def orderDataIn(self,orderData):
        '''从小策略生成的下单信号集中再传进来
        orderData=[{'strategy1':orderDict1,'strategy2':orderDict2}] '''
        self.orderList=orderData
    
    def settingSocket(self,address,port):
        '''关于端口通信的设置'''
        self.addr=address
        self.port=port
        self.socket.connect((self.addr,self.port))
    
    def setCSV(self,csv_heazder):
        '''设置csv的header'''
        self.csv_header=csv_heazder

    def setFileName(self,name):
        '''设置保存csv文件的名字'''
        self.file_name=name

    # ---------------------------------------------------------------------
    # 数据处理部分
    def settingCSV(self):
        '''与保存到本地CSV有关的设置'''
        self.csv_header=['strategy_name','side','symbol','price','volume','time']

    def strToDict(self,data_str):
        '''把字典字符串转换成字典'''
        try:
            # 优先使用json.loads把字符串转成字典结构
            data=json.loads(data_str)
        except json.decoder.JSONDecodeError:    
            data=eval(data_str)

        if isinstance(data,dict):
            pass
        else:
            raise KeyError('传进大策略的数据不是字典，注意')

        return data

    def checkStrategyData(self,strategy_data):
        '''检查是新策略还是旧策略
        strategy_data=[{'strategy_name':['side',price,volume,datetime],...] '''
        if not self.strategy_data:
            # 策略名列表什么都没有的时候
            self.strategy_data=[]
            temp={strategy_data['strategy']:[strategy_data['side'],strategy_data['price'],strategy_data['volume'],strategy_data['time']]}
            self.strategy_data.append(temp)
        else:
            for i in self.strategy_data:
                # 策略名列表中已经存在了这个策略名字
                if strategy_data['strategy'] in i:
                    # 如果策略名已存在，就覆盖
                    i[strategy_data['strategy']]=[strategy_data['side'],strategy_data['price'],strategy_data['volume'],strategy_data['time']]
                else:
                    temp={strategy_data['strategy']:[strategy_data['side'],strategy_data['price'],strategy_data['volume'],strategy_data['time']]}
                    self.strategy_data.append(temp)
    
    def IsFullStrategyList(self,num):
        '''判断strategy_data的列表是否填满了所有小策略，填满则返回true不然返回false,num是小策略的个数'''
        if len(self.strategy_data)==num:
            return True
        else:
            return False

    def judgeAllStrategyResult(self,side,same_result_num):
        '''收集所有小策略的下单结果，如果side结果达到ame_result_num的数量则返回true，same_result_num是一个整型'''
        assert type(side) is str
        assert type(same_result_num) is int

        side_num=[0,0]                     # [买，卖]
        for result in self.strategy_data:
            if result[0]=='buy':
                side_num[0]+=1
            else:
                side_num[1]+=1
        
        if side=='buy' and side_num[0]>=same_result_num:
            return True
        elif side=='sell' and side_num[1]>=same_result_num:
            return True
        else:
            return False

    # -----------------------------------------------------------------------------------
    # 大策略逻辑部分
    def bigStrategyLogi(self,data):
        '''大策略执行逻辑，这里应该由用户实现,传过来的data一定包含策略名还有时间
        data={'strategy':name,'time':datetime,...} '''
        pass

    def bigStrategyOnOrder(self):
        '''大策略下单时被动触发的函数'''
        print('大策略下单了')
        self.save_file_path='测试大策略'
        self.save_file_name='hasaki_test'
        self.save_key_name='order'

        data=self.orderDictToCSVForm()
        self.save_big_order.setting(self.save_file_path,self.save_file_name,self.csv_header,data)

    # -------------------------------------------------------------------------------------
    # 辅助功能模块
    def saveTheOrder(self,data):
        '''保存最新的order,order=[{'strategy_name':[{'side':},{'price':},{'volume':},{'time':}] '''
        self.save.setting(self.save_file_path,self.save_file_name,self.save_key_name,data)
        self.save.save()

    def saveTheOrderForCalculate(self):
        '''保存正真触发的大策略下单，用于做分析'''
        pass
    
    def orderDictToCSVForm(self):
        '''把字典转换成元组，把大策略下单的order转换成保存成csv的元组'''
        if self.this_name:
            pass
        else:
            self.this_name='hasaki_None'

        self.big_order['time']=datetime.datetime.now()
        temp_tuple=(self.this_name,self.big_order['side'],self.big_order['target_symbol'],
                    self.big_order['price'],self.big_order['volume'],self.big_order['time'])

        return [temp_tuple]

    # ------------------------------------------------------------------------------------
    # 大策略的下单功能
    def buy(self,target_symbol,price,volume):
        '''大策略的下单'''
        self.big_order.clear()
        self.bigStrategyOnOrder()
        self.big_order['target_symbole']=target_symbol
        self.big_order['side']='buy'
        self.big_order['price']=price
        self.big_order['volume']=volume
    
    def sell(self,target_symbol,price,volume):
        '''大策略的下单'''
        self.big_order.clear()
        self.bigStrategyOnOrder()
        self.big_order['target_symbole']=target_symbol
        self.big_order['side']='sell'
        self.big_order['price']=price
        self.big_order['volume']=volume
    
    def cancelOrder(self,orderID=None):
        '''取消订单'''
        self.bigStrategyOnOrder()

    # ------------------------------------------------------------------------------------
    # 运行部分
    def run(self):
        self.settingCSV()
        while 1:
            data_str=self.socket.recv(2000).decode()
            data=self.strToDict(data_str)
            self.checkStrategyData(data)
            self.bigStrategyLogi(data)